package com.pitop.core.tools;

import com.alibaba.fastjson.JSON;
import com.pitop.core.entity.BeanRet;
import com.pitop.core.tools.security.Md5;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.util.Base64Utils;

import java.io.IOException;
import java.util.Map;

/**
 * http 工具类的封装
 * 主要用于post，get，put，delete等标准http协议的请求
 * 此封装采用okhttp作为封装基础，具体用法按照okhttp的特性进行封装
 *
 * @author www.pi-top.com
 */
@Slf4j
public class HttpTools {

    /**
     * 通过post方式进行网络接口调用
     * 1.封装数据并对数据进行unicode转码以及base64加密
     * 2.请求远程接口并将返回结果进行标准封装返回
     *
     * @param url   请求地址 http://xxx/xxx/xxx
     * @param param 参数
     * @return BeanRet
     */
    public static BeanRet post(String url, String token, Object param) {
        if (param == null) {
            return BeanRet.create();
        }
        //1.封装数据并对数据进行unicode转码以及base64加密
        String json = JSON.toJSONString(param);
        log.debug(json);
        String unicodeStr = StringTools.Cn2UniCode(json);//进行unicode转码
        String base64Json = Base64Utils.encodeToString(unicodeStr.getBytes());//base64加密
        Map<String, Object> paraMap = new HashedMap();
        paraMap.put("json", base64Json);
        log.debug(base64Json);

        //2.请求远程接口并将返回结果进行标准封装返回
        url = url + "?md5=" + Md5.md5(base64Json);
        //请求远程接口
        log.debug("远程接口===> " + url);
        BeanRet beanRet = okHttpCall(url, JSON.toJSONString(paraMap), token, "POST");
        return beanRet;
    }

    /**
     * 通过post方式进行网络接口调用
     *
     * @param url   请求地址 http://xxx/xxx/xxx
     * @param param 参数
     * @return BeanRet
     */
    public static BeanRet post(String url, String token, Map<String, Object> param) {
        BeanRet beanRet = okHttpCall(url, JSON.toJSONString(param), token, "POST");
        return beanRet;
    }

    /**
     * 通过post方式进行网络接口调用
     *
     * @param url   请求地址 http://xxx/xxx/xxx
     * @param param 参数
     * @return BeanRet
     */
    public static BeanRet post(String url, String param, String token) {
        BeanRet beanRet = okHttpCall(url, param, token, "POST");
        return beanRet;
    }

    /**
     * 通过post方式进行网络接口调用
     *
     * @param url   请求地址 http://xxx/xxx/xxx
     * @param param 参数
     * @return BeanRet
     */
    public static BeanRet get(String url, String param) {
        BeanRet beanRet = okHttpCall(url, param, "GET");
        return beanRet;
    }


    /**
     * http网络请求封装
     *
     * @param url           请求地址 http://xxx/xxx/xxx
     * @param param         参数
     * @param requestMethod 请求类型支持POST/GET
     * @return BeanRet
     */
    private static BeanRet okHttpCall(String url, String param, String requestMethod) {
        return okHttpCall(url, param, null, requestMethod);
    }

    /**
     * http网络请求封装 用于携带token的
     *
     * @param url           请求地址 http://xxx/xxx/xxx
     * @param param         参数
     * @param token         验证token
     * @param requestMethod 请求类型支持POST/GET
     * @return
     */
    private static BeanRet okHttpCall(String url, String param, String token, String requestMethod) {
        try {
            Request request = null;
            if ("POST".equals(requestMethod)) {
                RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param);
                log.debug("requestBody >> " + requestBody);
                if (token != null) {
                    request = new Request.Builder()
                            .url(url)
                            .post(requestBody)
                            .addHeader("accept", "application/json")
                            .addHeader("token", token)
                            .build();
                } else {
                    request = new Request.Builder()
                            .url(url)
                            .post(requestBody)
                            .addHeader("accept", "application/json")
                            .build();
                }
                log.debug("request >> " + request);
            } else if ("GET".equals(requestMethod)) {
                if (token != null) {
                    request = new Request.Builder()
                            .url(url)
                            .addHeader("token", token)
                            .build();
                } else {
                    request = new Request.Builder()
                            .url(url)
                            .build();
                }
                log.debug("request >> " + request);
            }
            OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
            Response response = okHttpClient.newCall(request).execute();
            String result = response.body().string().trim();
            if (response.isSuccessful()) {
                log.debug("result << " + result);
                BeanRet beanRet = JSON.parseObject(result, BeanRet.class);
                return beanRet;
            } else {
                log.warn("网络请求失败返回结果为 << " + result);
                return BeanRet.create(false, "网络异常");
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return BeanRet.create(false, "网络异常");
    }
}
